home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OWLSRC.PAK / SLIDER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  17.3 KB  |  765 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1993, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.9  $
  6. //
  7. // Implementation of TSlider, slider UI widget abstract base class.
  8. //----------------------------------------------------------------------------
  9. #pragma hdrignore SECTION
  10. #include <owl/pch.h>
  11. #if !defined(OWL_SLIDER_H)
  12. # include <owl/slider.h>
  13. #endif
  14. #if !defined(OWL_DC_H)
  15. # include <owl/dc.h>
  16. #endif
  17. #if !defined(OWL_COMMCTRL_H)
  18. # include <owl/commctrl.h>
  19. #endif
  20.  
  21. OWL_DIAGINFO;
  22.  
  23. #if !defined(SECTION) || SECTION == 1
  24.  
  25. DEFINE_RESPONSE_TABLE1(TSlider, TScrollBar)
  26. #if !defined(OWL_NATIVECTRL_ALWAYS)
  27.   EV_WM_GETDLGCODE,
  28.   EV_WM_PAINT,
  29.   EV_WM_LBUTTONDOWN,
  30.   EV_WM_MOUSEMOVE,
  31.   EV_WM_LBUTTONUP,
  32.   EV_WM_LBUTTONDBLCLK,
  33.   EV_WM_KEYDOWN,
  34.   EV_WM_SETFOCUS,
  35.   EV_WM_KILLFOCUS,
  36. #endif
  37. END_RESPONSE_TABLE;
  38.  
  39. TSize  TSlider::MouseOffset;
  40. TDC*   TSlider::SlideDC = 0;
  41.  
  42. //
  43. // Always use the common control when available for sliders.
  44. //
  45. TNativeUse TSlider::ClassNativeUse = nuAlways;
  46.  
  47. //
  48. // Constructor for a TSlider object
  49. //
  50. TSlider::TSlider(TWindow*        parent,
  51.                  int             id,
  52.                  int x, int y, int w, int h,
  53.                  TResId          thumbResId,
  54.                  TModule*        module)
  55. :
  56.   TScrollBar(parent, id, x, y, w, h, true, module),
  57.   ThumbResId(thumbResId),
  58.   ThumbRect(0, 0, 0, 0)  // This will get setup whwn bitmap is loaded
  59. {
  60.   SetRange(0, 100);
  61.   Pos = 0;
  62.   ThumbRgn = 0;
  63.   TicGap = Range/10;  // Setup 10 evenly spaced tics by default, no array
  64.   Tics = 0;
  65.   TicCount = 0;
  66.   SlotThick = 4;      // Default for all sliders
  67.   Snap = true;
  68.   SelStart = SelEnd = 0;
  69.  
  70.   Sliding = false;
  71.  
  72. #if !defined(OWL_NATIVECTRL_NEVER)
  73.   NativeUse = TCommCtrl::IsAvailable() ? ClassNativeUse : nuNever;
  74. #else
  75.   NativeUse = nuNever;
  76. #endif
  77. }
  78.  
  79. //
  80. // Constructor for a TSlider object created from resource
  81. //
  82. TSlider::TSlider(TWindow* parent, int resId, TResId thumbResId, TModule* module)
  83. :
  84.   TScrollBar(parent, resId, module),
  85.   ThumbResId(thumbResId),
  86.   ThumbRect(0, 0, 0, 0)  // This will get setup whwn bitmap is loaded
  87. {
  88.   SetRange(0, 100);
  89.   Pos = 0;
  90.   ThumbRgn = 0;
  91.   TicGap = Range/10;  // Setup 10 evenly spaced tics by default, no array
  92.   Tics = 0;
  93.   TicCount = 0;
  94.   SlotThick = 4;      // Default for all sliders
  95.   Snap = true;
  96.   SelStart = SelEnd = 0;
  97.  
  98.   Sliding = false;
  99.  
  100. #if !defined(OWL_NATIVECTRL_NEVER)
  101.   NativeUse = TCommCtrl::IsAvailable() ? ClassNativeUse : nuNever;
  102. #else
  103.   NativeUse = nuNever;
  104. #endif
  105. }
  106. //
  107. //
  108. //
  109. TSlider::~TSlider()
  110. {
  111.   delete[] Tics;
  112.   delete ThumbRgn;
  113.   delete SlideDC;
  114. }
  115.  
  116. //
  117. // Check & set the slider range
  118. //
  119. void
  120. TSlider::SetRange(int min, int max, bool redraw)
  121. {
  122.   Min = min;
  123.   Max = max;
  124.   if (Max > Min)
  125.     Range = Max - Min;
  126.   else if (Min > Max)
  127.     Range = Min - Max;
  128.   else
  129.     Range = 1;
  130.  
  131. #if !defined(OWL_NATIVECTRL_NEVER)
  132.   if ((NativeUse & nuUsing) && GetHandle()) {
  133. //    TParam2 p2 = (Attr.Style & TBS_VERT) ? MkParam2(max, min) : MkParam2(min, max);
  134.     TParam2 p2 = MkParam2(min, max);
  135.     SendMessage(TBM_SETRANGE, redraw, p2);  // Swapped for vertical
  136.   }
  137. #endif
  138. }
  139.  
  140. //
  141. // Set the position of the thumb & always redraw
  142. //
  143. void
  144. TSlider::SetPosition(int pos)
  145. {
  146.   SetPosition(pos, true);
  147. }
  148.  
  149. //
  150. // Set the position of the thumb w/ optional redraw
  151. //
  152. void
  153. TSlider::SetPosition(int pos, bool redraw)
  154. {
  155.   // Constrain pos to be in the range "Min .. Max" & snap to tics if enabled
  156.   //
  157.   pos = SnapPos(pos);
  158.  
  159.   // Slide thumb to new position, converting pos to pixels
  160.   //
  161.   if (GetHandle()) {
  162.     if (NativeUse & nuUsing) {
  163.       SendMessage(TBM_SETPOS, redraw, pos);
  164.     }
  165. #if !defined(OWL_NATIVECTRL_ALWAYS)
  166.     else {
  167.       if (SlideDC)
  168.         SlideThumb(*SlideDC, pos);
  169.       else
  170.         SlideThumb(TClientDC(GetHandle()), pos);
  171.     }
  172. #endif
  173.   }
  174.   Pos = pos;
  175. }
  176.  
  177. //
  178. // Set the ruler evenly spaced tics and snap. Snapping is not supported in
  179. // native currently
  180. //
  181. void
  182. TSlider::SetRuler(int ticGap, bool snap)
  183. {
  184.   TicGap = ticGap;
  185.   Snap = snap;
  186.   delete[] Tics;
  187.   Tics = 0;
  188.  
  189.   if (GetHandle()) {
  190.     if (NativeUse & nuUsing)
  191.       SendMessage(TBM_SETTICFREQ, ticGap, 0);
  192. #if !defined(OWL_NATIVECTRL_ALWAYS)
  193.     else
  194.       Invalidate();  
  195. #endif
  196.   }
  197. }
  198.  
  199. //
  200. // Set the ruler custom tics and snap. Snapping is not supported in native
  201. // currently
  202. //
  203. void
  204. TSlider::SetRuler(int tics[], int ticCount, bool snap)
  205. {
  206.   PRECONDITION(tics || ticCount == 0);  // A 0 tics array is only OK if no tics
  207.  
  208.   // Alloc the array if the size is different, or we dont have one. Then copy
  209.   // the tic positions
  210.   //
  211.   if (ticCount > TicCount || !Tics) {
  212.     delete[] Tics;
  213.     Tics = ticCount ? new int[ticCount] : 0;
  214.   }
  215.   for (int i = 0; i < ticCount; i++)
  216.     if (tics[i] >= Min && tics[i] <= Max)  // Ignore out of range tics
  217.       Tics[i] = tics[i];
  218.   TicCount = ticCount;
  219.  
  220.   Snap = snap;
  221.  
  222.   if (GetHandle()) {
  223.     if (NativeUse & nuUsing) {
  224.       SendMessage(TBM_CLEARTICS, false);
  225.       for (int i = 0; i < TicCount; i++)
  226.         SendMessage(TBM_SETTIC, i, tics[i]);
  227.     }
  228. #if !defined(OWL_NATIVECTRL_ALWAYS)
  229.     else
  230.       Invalidate();  
  231. #endif
  232.   }
  233. }
  234.  
  235. //
  236. // Set a selection range for the slider.
  237. // Requires that TBS_ENABLESELRANGE style attribute be set.
  238. //
  239. void
  240. TSlider::SetSel(int start, int end, bool redraw)
  241. {
  242.   // Save selection state
  243.   //
  244.   SelStart = start;
  245.   SelEnd = end;
  246.  
  247.   if (GetHandle()) {
  248.     if (NativeUse & nuUsing)
  249.       SendMessage(TBM_SETSEL, redraw, MkUint32(uint16(start), uint16(end)));
  250. #if !defined(OWL_NATIVECTRL_ALWAYS)
  251.     else
  252.       Invalidate(); 
  253. #endif
  254.   }
  255. }
  256.  
  257. //
  258. // Get the selection range from the slider.
  259. // Requires that TBS_ENABLESELRANGE style attribute be set.
  260. //
  261. void
  262. TSlider::GetSel(int& start, int& end)
  263. {
  264.   if (GetHandle()) {
  265.     if (NativeUse & nuUsing) {
  266.       start = (int)SendMessage(TBM_GETSELSTART);
  267.       end = (int)SendMessage(TBM_GETSELEND);
  268.     }
  269. #if !defined(OWL_NATIVECTRL_ALWAYS)
  270. #endif
  271.   }
  272.   // Resync selection state
  273.   //
  274.   SelStart = start;
  275.   SelEnd = end;
  276. }
  277.  
  278. //----------------------------------------------------------------------------
  279. // Protected implementation
  280.  
  281. //
  282. // Return the windows system class name that this slider is basing itself on.
  283. // It depends on if NativeUse&nuUsing set.
  284. //
  285. char far*
  286. TSlider::GetClassName()
  287. {
  288. #if defined(OWL_NATIVECTRL_ALWAYS)
  289.   PRECONDITION(TCommCtrl::IsAvailable());
  290.   NativeUse = TNativeUse(NativeUse | nuUsing);
  291.   return TRACKBAR_CLASS;
  292.  
  293. #elif defined(OWL_NATIVECTRL_NEVER)
  294.   NativeUse = TNativeUse(NativeUse & ~nuUsing);
  295.   return TScrollBar::GetClassName();
  296.  
  297. #else
  298.   if ((NativeUse & nuSuggestion) >= nuDontCare && TCommCtrl::IsAvailable())
  299.     NativeUse = TNativeUse(NativeUse | nuUsing);
  300.   else
  301.     NativeUse = TNativeUse(NativeUse & ~nuUsing);
  302.  
  303.   if (NativeUse & nuUsing) {
  304.     if (!Tics)
  305.       Attr.Style |= TBS_AUTOTICKS;
  306.     return TRACKBAR_CLASS;
  307.   }
  308.   // Just use the generic owl class with our own name, since we don't need the
  309.   // native scrollbar window class for any implementation
  310.   //
  311.   return "OWL_Slider";
  312. #endif
  313. }
  314.  
  315. //
  316. // Setup slider window
  317. //
  318. void
  319. TSlider::SetupWindow()
  320. {
  321.   TScrollBar::SetupWindow();
  322.  
  323. #if !defined(OWL_NATIVECTRL_ALWAYS)
  324.  
  325.   // For internal impl, setup the thumb rect & region, & set bkgnd color to
  326.   // transparent since we'll always erase as we paint to avoid flicker
  327.   //
  328.   if (!(NativeUse & nuUsing)) {
  329.     TPoint point = PosToPoint(Pos);
  330.     TDib  thumbDib(*GetModule(), ThumbResId);
  331.     ThumbRect.SetWH(point.x, point.y, thumbDib.Width()/2, thumbDib.Height());
  332.     SetupThumbRgn();
  333.     SetBkgndColor(TColor::Transparent);
  334.   }
  335.   // For native implementation, pass our setup properties to the native control
  336.   //
  337.   else {
  338. #endif
  339.  
  340.     SetRange(Min, Max);
  341.     if (Tics)
  342.       SetRuler(Tics, TicCount, Snap);
  343.     else
  344.       SetRuler(TicGap, Snap);
  345.     SetSel(SelStart, SelEnd, false);
  346.     SetPosition(Pos, true);
  347.  
  348. #if !defined(OWL_NATIVECTRL_ALWAYS)
  349.   }
  350. #endif
  351. }
  352.  
  353. //
  354. // Constrain pos to be in the range "Min .. Max" &
  355. // perform 'Snap'ing if enabled by rounding pos to nearest TicGap
  356. //
  357. int
  358. TSlider::SnapPos(int pos)
  359. {
  360.   if (pos > Max)
  361.     pos = Max;
  362.  
  363.   else if (pos < Min)
  364.     pos = Min;
  365.  
  366.   return Snap ? (((pos-Min)+TicGap/2)/TicGap)*TicGap + Min : pos;
  367. }
  368.  
  369. // Leave the whole implemenation out if built with OWL_NATIVECTRL_ALWAYS
  370. //
  371. #if !defined(OWL_NATIVECTRL_ALWAYS)
  372.  
  373. //
  374. // Setup region that defines the thumb shape for this slider class.
  375. // default region is a simple bounding rect, but could be any shape.
  376. //
  377. void
  378. TSlider::SetupThumbRgn()
  379. {
  380.   if (!ThumbRgn)
  381.     ThumbRgn = new TRegion(ThumbRect);
  382. }
  383.  
  384. //
  385. // Slide the thumb & perform necessary blitting & painting.
  386. // Assumes that Pos, Min & Max are up to date.
  387. //
  388. void
  389. TSlider::SlideThumb(TDC& dc, int pos)
  390. {
  391.   TPoint point = PosToPoint(pos);
  392.  
  393.   GetBkColor(dc);
  394.   if (ThumbRgn) {
  395.     TRegion  oldRgn(ThumbRect);
  396.     TRect    newThumbRect(point, ThumbRect.Size());
  397.  
  398.     *ThumbRgn += point-ThumbRect.TopLeft();
  399.  
  400.     dc.SelectClipRgn(*ThumbRgn);
  401.     dc.BitBlt(newThumbRect, dc, ThumbRect.TopLeft());
  402.  
  403.     ThumbRect = newThumbRect;
  404.  
  405.     oldRgn -= *ThumbRgn;
  406.     dc.SelectClipRgn(oldRgn);
  407.     PaintSlot(dc);
  408.   }
  409.   else {
  410.     ThumbRect.MoveTo(point.x, point.y);
  411.     PaintSlot(dc);
  412.     PaintThumb(dc);
  413.   }
  414.  
  415.   {
  416.     TClientDC dc(*this);
  417.     THatch8x8Brush br(THatch8x8Brush::Hatch11F1,
  418.                       TColor::White, TColor::Sys3dFace); 
  419.     dc.FrameRect(GetClientRect(), br);
  420.   }
  421. }
  422.  
  423. //
  424. // Paint the thumb itself using a resource DIB translated to the current system
  425. // button colors. Overlaps the slot.
  426. //
  427. void
  428. TSlider::PaintThumb(TDC& dc)
  429. {
  430.   TDib  thumbDib(*GetModule(), ThumbResId);
  431.   thumbDib.MapUIColors(
  432.     TDib::MapFace|TDib::MapText|TDib::MapShadow|TDib::MapHighlight,
  433.     &dc.GetBkColor()
  434.   );
  435.   int  dibX = (Sliding || !IsWindowEnabled()) ? thumbDib.Width()/2 : 0;
  436.   dc.SetDIBitsToDevice(ThumbRect, TPoint(dibX, 0), thumbDib);
  437. }
  438.  
  439. //
  440. // Get & release a brush obtained from our parent window for use in painting
  441. // background areas in this control.
  442. //
  443. void
  444. TSlider::GetBkColor(TDC& dc)
  445. {
  446. #if defined(BI_PLAT_WIN32)
  447.   Parent->HandleMessage(WM_CTLCOLORSTATIC,
  448.                         TParam1(HDC(dc)),
  449.                         TParam2(GetHandle()));
  450. #else
  451.   Parent->HandleMessage(WM_CTLCOLOR,
  452.                         TParam1(HDC(dc)),
  453.                         MkParam2(GetHandle(), CTLCOLOR_STATIC));
  454. #endif
  455.   BkColor = dc.GetBkColor();
  456. }
  457.  
  458. //
  459. // Make sure we get cursor movement keys to move the thumb
  460. //
  461. uint
  462. TSlider::EvGetDlgCode(MSG far*)
  463. {
  464.   return DLGC_WANTARROWS;
  465. }
  466.  
  467. //
  468. // Paint the whole slider: ruler, slot & thumb
  469. //
  470. void
  471. TSlider::EvPaint()
  472. {
  473.   if (NativeUse & nuUsing) {
  474.     DefaultProcessing();
  475.     return;
  476.   }
  477.  
  478.   if (ThumbRgn) {                   // use thumb region if avalable
  479.     TRegion updateRgn;
  480.     GetUpdateRgn(updateRgn);
  481.  
  482.     TPaintDC  dc(*this);
  483.  
  484.     GetBkColor(dc);
  485.  
  486.     TRegion thumbClip = *ThumbRgn;  // set clip to intersect of update & thumb
  487.     thumbClip &= updateRgn;
  488.     dc.SelectClipRgn(thumbClip);
  489.     PaintThumb(dc);
  490.  
  491.     updateRgn -= thumbClip;
  492.     dc.SelectClipRgn(updateRgn);    // set clip to update minus thumb
  493.     ValidateRgn(*ThumbRgn);
  494.     PaintSlot(dc);
  495.     PaintRuler(dc);
  496.   }
  497.   else {                          // no region, thumb will flicker a little
  498.     TPaintDC  dc(*this);
  499.  
  500.     GetBkColor(dc);
  501.     PaintSlot(dc);
  502.     PaintRuler(dc);
  503.     PaintThumb(dc);
  504.   }
  505.   if (GetFocus() == GetHandle()) {
  506.     TClientDC dc(*this);
  507.     dc.FrameRect(GetClientRect(), THatch8x8Brush(THatch8x8Brush::Hatch11F1));
  508.   }
  509. }
  510.  
  511. //
  512. // If a button down on the thumb, then enter sliding state.
  513. // If in the slot, pg up or down. If on the ruler, jump there.
  514. //
  515. void
  516. TSlider::EvLButtonDown(uint /*modKeys*/, TPoint& point)
  517. {
  518.   if (NativeUse & nuUsing) {
  519.     DefaultProcessing();
  520.     return;
  521.   }
  522.  
  523.   if (GetFocus() != GetHandle())
  524.     SetFocus();
  525.  
  526.   int scrollCode = HitTest(point);
  527.   switch (scrollCode) {
  528.     case SB_THUMBPOSITION:
  529.       NotifyParent(scrollCode, SnapPos(PointToPos(point)));
  530.       break;
  531.  
  532.     case SB_LINEUP:
  533.     case SB_LINEDOWN:
  534.     case SB_PAGEUP:
  535.     case SB_PAGEDOWN:
  536.       NotifyParent(scrollCode);
  537.       break;
  538.  
  539.     case SB_THUMBTRACK: {
  540.       Sliding = true;
  541.       SetCapture();
  542.       SlideDC = new TClientDC(GetHandle());  // keep this dc around while sliding
  543.  
  544.       GetBkColor(*SlideDC);  // repaint thumb in pressed state
  545.       PaintThumb(*SlideDC);
  546.  
  547.       MouseOffset = point-ThumbRect.TopLeft();
  548.       point -= MouseOffset;
  549.       int pos = SnapPos(PointToPos(point));// keep thumb on track & on pos units
  550.       NotifyParent(9, pos);     // undocumented 'begin track' code
  551.       NotifyParent(SB_THUMBTRACK, pos);
  552.     }
  553.   }
  554. }
  555.  
  556. //
  557. // If sliding then either slide thumb, or detect a lost button up & simulate
  558. // it.
  559. //
  560. void
  561. TSlider::EvMouseMove(uint modKeys, TPoint& point)
  562. {
  563.   if (NativeUse & nuUsing) {
  564.     DefaultProcessing();
  565.     return;
  566.   }
  567.  
  568.   if (Sliding && SlideDC) {
  569.     if (!(modKeys&MK_LBUTTON)) {
  570.       EvLButtonUp(modKeys, point);    // we missed a lbutton up somehow...
  571.       return;
  572.     }
  573.     // Keep thumb on track & on pos units
  574.     //
  575.     NotifyParent(SB_THUMBTRACK, SnapPos(PointToPos(point - MouseOffset)));
  576.   }
  577. }
  578.  
  579. //
  580. // Handle button messages if we are sliding by releasing capture & ending
  581. // sliding state
  582. //
  583. void
  584. TSlider::EvLButtonUp(uint /*modKeys*/, TPoint& point)
  585. {
  586.   if (NativeUse & nuUsing) {
  587.     DefaultProcessing();
  588.     return;
  589.   }
  590.  
  591.   int pos = SnapPos(PointToPos(point - MouseOffset));
  592.   if (Sliding) {
  593.     Sliding = false;
  594.     NotifyParent(SB_THUMBPOSITION, pos);
  595.  
  596.     GetBkColor(*SlideDC);   // repaint thumb in released state
  597.     if (ThumbRgn)
  598.       SlideDC->SelectClipRgn(*ThumbRgn);
  599.     PaintThumb(*SlideDC);
  600.  
  601.     ReleaseCapture();
  602.     delete SlideDC;
  603.     SlideDC = 0;
  604.   }
  605.   NotifyParent(SB_ENDSCROLL, pos);
  606. }
  607.  
  608. //
  609. // Catch double clicks and eat them
  610. //
  611. void
  612. TSlider::EvLButtonDblClk(uint modKeys, TPoint& point)
  613. {
  614.   if (NativeUse & nuUsing) {
  615.     TControl::EvLButtonDblClk(modKeys, point);
  616.   }
  617.   else {
  618.     // For our purpose, a DoubleClick's just another click...
  619.     //
  620.     EvLButtonDown(modKeys, point);
  621.   }
  622. }
  623.  
  624. //
  625. // Translate key messages to scroll events w/ repeat.
  626. //
  627. void
  628. TSlider::EvKeyDown(uint key, uint repeatCount, uint /*flags*/)
  629. {
  630.   if (NativeUse & nuUsing) {
  631.     DefaultProcessing();
  632.     return;
  633.   }
  634.  
  635.   static int KeyToCode[] = {
  636.     SB_PAGEUP,    // VK_PRIOR
  637.     SB_PAGEDOWN,  // VK_NEXT
  638.     SB_BOTTOM,    // VK_END
  639.     SB_TOP,       // VK_HOME
  640.     SB_LINEUP,    // VK_LEFT(same as SB_LINELEFT)
  641.     SB_LINEUP,    // VK_UP
  642.     SB_LINEDOWN,  // VK_RIGHT(same as SB_LINERIGHT)
  643.     SB_LINEDOWN   // VK_DOWN
  644.   };
  645.  
  646.   if (key >= VK_PRIOR && key <= VK_DOWN) {
  647.     for (uint i = 0; i < repeatCount; i++)
  648.       NotifyParent(KeyToCode[key-VK_PRIOR], Pos);
  649.     NotifyParent(SB_ENDSCROLL, Pos);
  650.   }
  651. }
  652.  
  653. //
  654. // Paint a focus rect when we have focus. Remove it when we lose focus
  655. //
  656. void
  657. TSlider::EvSetFocus(THandle /*hLostFocus*/)
  658. {
  659.   if (NativeUse & nuUsing) {
  660.     DefaultProcessing();
  661.     return;
  662.   }
  663.   TClientDC dc(*this);
  664.   THatch8x8Brush br(THatch8x8Brush::Hatch11F1,
  665.                     TColor::White, TColor::Sys3dFace); 
  666.  
  667.   dc.FrameRect(GetClientRect(), br);
  668. }
  669.  
  670. //
  671. //
  672. //
  673. void
  674. TSlider::EvKillFocus(THandle hGetFocus)
  675. {
  676.   if (NativeUse & nuUsing) {
  677.     DefaultProcessing();
  678.     return;
  679.   }
  680.   TClientDC dc(*this);
  681.   TBrush br(TColor::Sys3dFace);
  682.   dc.FrameRect(GetClientRect(), br);
  683.  
  684.   TScrollBar::EvKillFocus(hGetFocus); // Need to let TWindow do focus save
  685. }
  686.  
  687. #endif  // !defined(OWL_NATIVECTRL_ALWAYS)
  688.  
  689. #endif
  690. #if !defined(SECTION) || SECTION == 2
  691.  
  692. IMPLEMENT_ABSTRACT_STREAMABLE1(TSlider, TScrollBar);
  693.  
  694. #if !defined(BI_NO_OBJ_STREAMING)
  695.  
  696. //
  697. //
  698. //
  699. void*
  700. TSlider::Streamer::Read(ipstream& is, uint32 version) const
  701. {
  702.   TSlider* o = GetObject();
  703.   ReadBaseObject((TScrollBar*)o, is);
  704.   is >> o->Min
  705.      >> o->Max
  706.      >> o->Pos
  707.      >> o->ThumbResId
  708.      >> o->ThumbRect;
  709.   if (version == 1) {
  710.     TRect tmpRect;
  711.     is >> tmpRect;     // dummy CaretRect for compatibilty with stream v1
  712.   }
  713.   is >> o->TicGap
  714.      >> o->Snap;
  715.  
  716.   // In stream version 2 and above, a tic array with count is written, as well
  717.   // as a selection range
  718.   //
  719.   if (version >= 2) {
  720.     is >> o->TicCount;
  721.     o->Tics = o->TicCount ? new int[o->TicCount] : 0;
  722.     for (int i = 0; i < o->TicCount; i++)
  723.       is >> o->Tics[i];
  724.  
  725.     is >> o->SelStart
  726.        >> o->SelEnd;
  727.   }
  728.  
  729.   o->SetRange(o->Min, o->Max);  // let it calculate Range
  730.   return o;
  731. }
  732.  
  733. //
  734. //
  735. //
  736. void
  737. TSlider::Streamer::Write(opstream& os) const
  738. {
  739.   TSlider* o = GetObject();
  740.   WriteBaseObject((TScrollBar*)o, os);
  741.   os << o->Min
  742.      << o->Max
  743.      << o->Pos
  744.      << o->ThumbResId
  745.      << o->ThumbRect
  746.      << o->TicGap
  747.      << o->Snap
  748.      << o->TicCount;
  749.  
  750.   // In stream version 2 and above, a tic array with count is written, as well
  751.   // as a selection range
  752.   //
  753.   os << o->TicCount;
  754.   for (int i = 0; i < o->TicCount; i++)
  755.     os << o->Tics[i];
  756.   int d1,d2;
  757.   o->GetSel(d1,d2);     // Force retrieval of current selection before writing
  758.   os << o->SelStart
  759.      << o->SelEnd;
  760. }
  761.  
  762. #endif  // if !defined(BI_NO_OBJ_STREAMING)
  763.  
  764. #endif
  765.